import { useMessage } from '@/hooks/useMessage';
import { useI18n } from '@/locale/index';
import { request } from '@/utils/request/uni';
import { isString } from '@/utils/is';
import { AjaxResult, ErrorMessageMode } from '#/request';

// TODO: 别忘加更改环境变量的 VITE_UPLOAD_BASEURL 地址。
const VITE_UPLOAD_BASEURL = import.meta.env.VITE_UPLOAD_BASEURL;

/**
 * useUpload 是一个定制化的请求钩子，用于处理上传文件。
 * @param formData 额外传递给后台的数据，如{name: '大站长'}。
 * @param url 请求的地址，默认：VITE_UPLOAD_BASEURL。
 * @param mediaType 文件类型：默认：image。
 * @param name 文件对应的 key , 开发者在服务器端通过这个 key 可以获取到文件二进制内容。默认：file。
 * @param errorMessageMode 错误消息提示模式
 * @returns 返回一个对象{loading, progress, error, data, run}，包含请求的加载状态、错误信息、响应数据和手动触发请求的函数。
 */
export default function useUpload<T = AjaxResult>(
  formData: Record<string, any> = {},
  url: string = VITE_UPLOAD_BASEURL,
  mediaType: 'video' | 'image' = 'image',
  name: string = 'file',
  errorMessageMode: ErrorMessageMode = 'message',
) {
  const loading = ref(false);
  const progress = ref<OnProgressEvent>({ progress: 0, loaded: 0, total: 0 });
  const error = ref(false);
  const data = ref<T>();

  const { t } = useI18n();
  const { toast, modal } = useMessage();

  /** 运行 */
  const run = async (
    _formData: Record<string, any> = formData,
    _url: string = url,
    _mediaType: 'video' | 'image' = mediaType,
    _name: string = name,
    _errorMessageMode: ErrorMessageMode = errorMessageMode,
  ) => {
    try {
      // #ifdef MP-WEIXIN
      // 微信小程序从基础库 2.21.0 开始， wx.chooseImage 停止维护，请使用 uni.chooseMedia 代替。
      // 微信小程序在2023年10月17日之后，使用本API需要配置隐私协议。
      uni.chooseMedia({
        count: 1,
        sizeType: ['original'],
        mediaType: [_mediaType],
        success: async (res) => {
          loading.value = true;

          try {
            const tempFile = res.tempFiles[0];
            const result = await request.uploadFile(
              {
                url: _url,
                filePath: tempFile.tempFilePath,
                name: _name,
                formData: _formData,
                onProgress: (event) => {
                  progress.value = {
                    progress: event.progress,
                    loaded: event.loaded,
                    total: event.total,
                  };
                },
              },
              {
                errorMessageMode: _errorMessageMode,
              },
            );
            data.value = result as T;
          } catch (err) {
            console.error('文件上传错误', err);
            error.value = true;
          } finally {
            loading.value = false;
          }
        },
        fail: (err) => {
          console.error('选择文件错误', err);
          error.value = true;
          const errMsg = isString(err) ? err : JSON.stringify(err);
          if (_errorMessageMode === 'modal') {
            modal.alert({ title: t('sys.api.errorTip'), content: errMsg });
          } else if (_errorMessageMode === 'message') {
            toast.error({
              content: errMsg,
            });
          }
        },
        complete: () => {
          // loading.value = false;
        },
      });
      // #endif
      // #ifndef MP-WEIXIN
      const chooseMedia = _mediaType === 'image' ? uni.chooseImage : uni.chooseVideo;
      chooseMedia({
        count: 1,
        sizeType: ['original'],
        success: async (res) => {
          loading.value = true;

          try {
            const tempFilePath = res.tempFilePaths[0];
            // const tempFile = res.tempFiles[0];
            const result = await request.uploadFile(
              {
                url: _url,
                filePath: tempFilePath,
                name: _name,
                formData: _formData,
                onProgress: (event) => {
                  progress.value = {
                    progress: event.progress,
                    loaded: event.loaded,
                    total: event.total,
                  };
                },
              },
              {
                errorMessageMode: _errorMessageMode,
              },
            );
            data.value = result as T;
          } catch (err) {
            console.error('文件上传错误', err);
            error.value = true;
          } finally {
            loading.value = false;
          }
        },
        fail: (err) => {
          console.error('选择文件错误', err);
          error.value = true;
          const errMsg = isString(err) ? err : JSON.stringify(err);
          if (_errorMessageMode === 'modal') {
            modal.alert({ title: t('sys.api.errorTip'), content: errMsg });
          } else if (_errorMessageMode === 'message') {
            toast.error({
              content: errMsg,
            });
          }
        },
        finally: () => {
          // loading.value = false;
        },
      });
      // #endif
    } catch {
      error.value = true;
    } finally {
      // loading.value = false;
    }
  };

  /** 中断下载 */
  const abort = async () => {
    loading.value = false;

    request.abort();
  };

  return { loading, progress, error, data, run, abort };
}
